package com.dzsw.netty.basic.future;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.FutureTask;
import java.util.concurrent.*;

@Slf4j
public class EventLoop implements Runnable {

    public static final int STATUS_ON = 1;

    public static final int STATUS_OFF = 0;

    private volatile int status = STATUS_ON;

    private Thread t;

    private BlockingQueue<Runnable> taskQueue = new LinkedBlockingQueue<>();

    public EventLoop() {
        t = new Thread(this);
        t.setName("Eventloop Thread ");
        t.start();
    }

    /**
     *
     * 使用interrupt()方法来中断线程是分两种情况的：
     *  1. 线程处于阻塞状态：如使用了sleep()，同步锁的wait()，socket中的receiver()，accept()等方法时，会使线程处于阻塞状态。
     *  当调用线程interrupt()方法时，会抛出InterruptException异常。阻塞中的那个方法抛出此异常，通过代码可以捕获此异常，然后跳
     *  出循环状态，从而让我们有机会结束这个线程的执行。并不是只要调用interrupt()方法，线程就会结束，实际上是不正确的，一定要先
     *  捕获InterruptException异常之后通过break来跳出循环，才能正常结束run()方法。
     *  2. 线程未处于阻塞状态：使用isInterrupted()判断线程的中断标志来退出循环。当使用interrupt()方法时，中断标志就会为true，
     *  和使用自定义的标志来控制循环是一样的道理。
     */
    public void stop() {
        status = STATUS_OFF;
        t.interrupt();
        System.out.println("stop, status is " + status);
    }

    public Future submit(Callable callable) throws Exception {
        FutureTask task = new FutureTask(callable);
        taskQueue.put(task);
        return task;
    }

    public void submit(Runnable runnable) throws Exception {
        taskQueue.put(runnable);
    }

    @Override
    public void run() {
        while (status == STATUS_ON) {
            System.out.println("Thread status is " + status + " ============================== ");
            try {
                Runnable task = taskQueue.take();
                task.run();
            } catch (InterruptedException e) {
                e.printStackTrace();
                break;
            }
        }
        System.out.println("Thread is completed.");
    }
}
